package cn.jtcoding.order.service.impl;

import cn.jtcoding.common.framework.enums.ApiResultCode;
import cn.jtcoding.common.framework.enums.OrderStatusEnum;
import cn.jtcoding.common.framework.enums.YesOrNo;
import cn.jtcoding.common.framework.exception.ApiException;
import cn.jtcoding.common.framework.pagehelper.PagedGridResult;
import cn.jtcoding.common.framework.vo.ApiResult;
import cn.jtcoding.item.pojo.dataobject.ItemsDO;
import cn.jtcoding.item.pojo.dataobject.ItemsSpecDO;
import cn.jtcoding.order.api.OrderService;
import cn.jtcoding.order.mapper.OrderItemsMapper;
import cn.jtcoding.order.mapper.OrderStatusMapper;
import cn.jtcoding.order.mapper.OrdersMapper;
import cn.jtcoding.order.pojo.bo.SubmitOrderBO;
import cn.jtcoding.order.pojo.dataobject.OrderItemsDO;
import cn.jtcoding.order.pojo.dataobject.OrderStatusDO;
import cn.jtcoding.order.pojo.dataobject.OrdersDO;
import cn.jtcoding.order.pojo.vo.MerchantOrdersVO;
import cn.jtcoding.order.pojo.vo.OrderVO;
import cn.jtcoding.order.service.impl.feign.ItemFeignService;
import cn.jtcoding.order.service.impl.feign.UserAddressFeignService;
import cn.jtcoding.user.pojo.dataobject.UserAddressDO;
import io.seata.spring.annotation.GlobalTransactional;
import org.n3r.idworker.Sid;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Propagation;
import org.springframework.transaction.annotation.Transactional;

import java.time.LocalDateTime;
import java.util.List;

@Service
public class OrderServiceImpl implements OrderService {

    @Autowired
    private OrdersMapper ordersMapper;
    @Autowired
    private OrderItemsMapper orderItemsMapper;
    @Autowired
    private OrderStatusMapper orderStatusMapper;
    @Autowired
    private Sid sid;

    @Autowired
    private UserAddressFeignService userAddressFeignService;
    @Autowired
    private ItemFeignService itemFeignService;

    @GlobalTransactional
    @Override
    public OrderVO createOrder(SubmitOrderBO submitOrderBO) {
        String userId = submitOrderBO.getUserId();
        String addressId = submitOrderBO.getAddressId();
        String itemSpecIds = submitOrderBO.getItemSpecIds();
        Integer payMethod = submitOrderBO.getPayMethod();
        String leftMsg = submitOrderBO.getLeftMsg();
        // 包邮费用设置为0
        Integer postAmount = 0;

        String orderId = sid.nextShort();

        ApiResult<UserAddressDO> userAddressResult = userAddressFeignService.queryUserAddress(userId, addressId);
        UserAddressDO address = userAddressResult.getData();
        if (address == null) {
            throw new ApiException(ApiResultCode.UNKNOWN_ERROR);
        }
        // 1. 新订单数据保存
        OrdersDO newOrder = new OrdersDO();
        newOrder.setId(orderId);
        newOrder.setUserId(userId);

        newOrder.setReceiverName(address.getReceiver());
        newOrder.setReceiverMobile(address.getMobile());
        newOrder.setReceiverAddress(address.getProvince() + " "
                                    + address.getCity() + " "
                                    + address.getDistrict() + " "
                                    + address.getDetail());

//        newOrder.setTotalAmount();
//        newOrder.setRealPayAmount();
        newOrder.setPostAmount(postAmount);
        newOrder.setPayMethod(payMethod);
        newOrder.setLeftMsg(leftMsg);

        newOrder.setIsComment(YesOrNo.NO.type);
        newOrder.setIsDelete(YesOrNo.NO.type);
        newOrder.setCreatedTime(LocalDateTime.now());
        newOrder.setUpdatedTime(LocalDateTime.now());


        //TODO 2. 循环根据itemSpecIds保存订单商品信息表
        String[] itemSpecIdArr = itemSpecIds.split(",");
        int buyCounts = submitOrderBO.getBuyCounts();
        int totalAmount = 0;    // 商品原价累计
        int realPayAmount = 0;  // 优惠后的实际支付价格累计
        for (String itemSpecId : itemSpecIdArr) {

            // TODO 整合redis后，商品购买的数量重新从redis的购物车中获取

            //TODO  2.1 根据规格id，查询规格的具体信息，主要获取价格
            ApiResult<ItemsSpecDO> itemsSpecResult = itemFeignService.queryItemSpecById(itemSpecId);
            ItemsSpecDO itemSpec = itemsSpecResult.getData();
            if (itemSpec == null) {
                throw new ApiException(ApiResultCode.UNKNOWN_ERROR);
            }
            totalAmount += itemSpec.getPriceNormal() * buyCounts;
            realPayAmount += itemSpec.getPriceDiscount() * buyCounts;

            // 2.2 根据商品id，获得商品信息以及商品图片
            String itemId = itemSpec.getItemId();
            ApiResult<ItemsDO> itemsResult = itemFeignService.queryItemById(itemId);
            ItemsDO item = itemsResult.getData();
            if (item == null) {
                throw new ApiException(ApiResultCode.UNKNOWN_ERROR);
            }

            ApiResult<String> mainImgResult = itemFeignService.queryItemMainImgById(itemId);
            String imgUrl = mainImgResult.getData();
            if (imgUrl == null) {
                throw new ApiException(ApiResultCode.UNKNOWN_ERROR);
            }

            //TODO 2.3 循环保存子订单数据到数据库
            String subOrderId = sid.nextShort();
            OrderItemsDO subOrderItem = new OrderItemsDO();
            subOrderItem.setId(subOrderId);
            subOrderItem.setOrderId(orderId);
            subOrderItem.setItemId(itemId);
            subOrderItem.setItemName(item.getItemName());
            subOrderItem.setItemImg(imgUrl);
            subOrderItem.setBuyCounts(buyCounts);
            subOrderItem.setItemSpecId(itemSpecId);
            subOrderItem.setItemSpecName(itemSpec.getName());
            subOrderItem.setPrice(itemSpec.getPriceDiscount());
            orderItemsMapper.addOrderItem(subOrderItem);

            //TODO 2.4 在用户提交订单以后，规格表中需要扣除库存
            itemFeignService.decreaseItemSpecStock(itemSpecId, buyCounts);
        }

        newOrder.setTotalAmount(totalAmount);
        newOrder.setRealPayAmount(realPayAmount);
        ordersMapper.addOrder(newOrder);

        // 3. 保存订单状态表
        OrderStatusDO waitPayOrderStatus = new OrderStatusDO();
        waitPayOrderStatus.setOrderId(orderId);
        waitPayOrderStatus.setOrderStatus(OrderStatusEnum.WAIT_PAY.type);
        waitPayOrderStatus.setCreatedTime(LocalDateTime.now());
        orderStatusMapper.addOrderStatus(waitPayOrderStatus);

        // 4. 构建商户订单，用于传给支付中心
        MerchantOrdersVO merchantOrdersVO = new MerchantOrdersVO();
        merchantOrdersVO.setMerchantOrderId(orderId);
        merchantOrdersVO.setMerchantUserId(userId);
        merchantOrdersVO.setAmount(0);
        merchantOrdersVO.setPayMethod(payMethod);

        // 5. 构建自定义订单vo
        OrderVO orderVO = new OrderVO();
        orderVO.setOrderId(orderId);
        orderVO.setMerchantOrdersVO(merchantOrdersVO);

        return orderVO;
    }

    @Transactional(propagation = Propagation.REQUIRED)
    @Override
    public void updateOrderStatus(String orderId, Integer orderStatus) {

        OrderStatusDO paidStatus = new OrderStatusDO();
        paidStatus.setOrderId(orderId);
        paidStatus.setOrderStatus(orderStatus);
        paidStatus.setPayTime(LocalDateTime.now());

        orderStatusMapper.updateOrderStatus(paidStatus);
    }

    @Transactional(propagation = Propagation.SUPPORTS)
    @Override
    public OrderStatusDO queryOrderStatusInfo(String orderId) {
        return orderStatusMapper.queryOrderStatusInfo(orderId);
    }

    @Transactional(propagation = Propagation.REQUIRED)
    @Override
    public void closeOrder() {
        // 查询所有未付款订单，判断时间是否超时（1天），超时则关闭交易
        List<OrderStatusDO> list = orderStatusMapper.queryWaitPayOrders();
        for (OrderStatusDO os : list) {
            // 获得订单创建时间
            LocalDateTime createdTime = os.getCreatedTime();
            // 和当前时间进行对比
            LocalDateTime time = createdTime.plusMinutes(30);
            if (!time.isAfter(LocalDateTime.now())) {
                // 超过30 min，关闭订单
                doCloseOrder(os.getOrderId());
            }
        }
    }

    @Override
    public PagedGridResult listUserOrders(String userId, Integer orderStatus, Integer page, Integer pageSize) {
        return null;
    }

    @Override
    public void updateDeliverOrderStatus(String orderId) {

    }

    @Override
    public boolean deleteOrder(String userId, String orderId) {
        return false;
    }

    @Override
    public OrdersDO queryMyOrder(String userId, String orderId) {
        return null;
    }

    @Transactional(propagation = Propagation.REQUIRED)
    void doCloseOrder(String orderId) {
        OrderStatusDO close = new OrderStatusDO();
        close.setOrderId(orderId);
        close.setOrderStatus(OrderStatusEnum.CLOSE.type);
        close.setCloseTime(LocalDateTime.now());
        orderStatusMapper.updateOrderStatus(close);
    }
}
